package com.pinfly.common.security;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.log4j.Logger;

import com.pinfly.common.crypto.CryptoException;

public class Password
{
    private static final Logger logger = Logger.getLogger (Password.class);

    public static byte[] getEncryptedPassword (String unEncrypted)
    {
        byte[] password = unEncrypted.getBytes ();
        byte[] hash = null;

        try
        {

            MessageDigest md5 = MessageDigest.getInstance ("MD5");
            md5.update (password);
            hash = md5.digest ();
        }
        catch (NoSuchAlgorithmException e)
        {
            logger.fatal ("Couldn't get MD5 algorithm", e);
        }

        return hash;
    }

    private static Cipher getCipher (String iPassword, int iMode) throws CryptoException
    {
        Cipher pbeCipher = null;

        try
        {
            PBEKeySpec pbeKeySpec;
            PBEParameterSpec pbeParamSpec;
            SecretKeyFactory keyFac;

            // Salt
            byte[] salt =
            { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c, (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };

            // Create PBE parameter set
            pbeParamSpec = new PBEParameterSpec (salt, 20);

            // get secret key
            pbeKeySpec = new PBEKeySpec (iPassword.toCharArray ());
            keyFac = SecretKeyFactory.getInstance ("PBEWithMD5AndDES");
            SecretKey pbeKey = keyFac.generateSecret (pbeKeySpec);

            // Create PBE Cipher
            pbeCipher = Cipher.getInstance ("PBEWithMD5AndDES");

            // Initialize PBE Cipher with key and parameters
            pbeCipher.init (iMode, pbeKey, pbeParamSpec);

        }
        catch (Exception ex)
        {
            /*
             * Possible exceptions are InvalidAlgorithmParameterException
             * InvalidKeyException InvalidKeySpecException
             * NoSuchAlgorithmException NoSuchPaddingException
             */
            String msg = "Error getting cipher";
            logger.fatal (msg, ex);
            throw new CryptoException (msg);
        }
        return pbeCipher;
    }

    public static byte[] encrypt (byte iCleartext[], String iPassword) throws CryptoException
    {
        byte[] ciphertext = null;

        Cipher pbeCipher = getCipher (iPassword, Cipher.ENCRYPT_MODE);

        try
        {
            ciphertext = pbeCipher.doFinal (iCleartext);

        }
        catch (Exception ex)
        {
            /*
             * Possible exceptions are BadPaddingException
             * IllegalBlockSizeException
             */

            String msg = "Error in encrypt";
            logger.fatal (msg, ex);
            throw new CryptoException (msg);
        }
        return ciphertext;
    }

    public static byte[] decrypt (byte iCiphertext[], String iPassword) throws CryptoException
    {
        byte[] cleartext = null;

        Cipher pbeCipher = getCipher (iPassword, Cipher.DECRYPT_MODE);

        try
        {
            cleartext = pbeCipher.doFinal (iCiphertext);

        }
        catch (Exception ex)
        {
            /*
             * Possible exceptions are BadPaddingException
             * IllegalBlockSizeException
             */
            String msg = "Error in decrypt";
            logger.fatal (msg, ex);
            throw new CryptoException (msg);
        }

        return cleartext;
    }

}
